home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ9203.ZIP
/
OOPASM.ASC
< prev
next >
Wrap
Text File
|
1992-01-24
|
26KB
|
694 lines
_AN OBJECT-ORIENTED ASSEMBLY LANGUAGE MACRO LIBRARY_
by Donald J. McSwain
[LISTING ONE]
Macro File: objects.mac
COMMENT % ===============================================================
Sets up stack, SI with object pointer, DX with message number, and calls
sendMsg procedure.
Passed: Obj - Name of receiving object; Msg - Message number
=========================================================================%
send MACRO Obj,Msg,ArgList
pushArgs ArgList ;Push arguments onto stack
IFIDN <Obj>,<Self> ;If object is Self
mov si,Wptr[Self] ;Get object ptr from it
ELSE
IFDIF <Obj>,<si> ;If object ptr not in SI
lea si,Obj ;Load SI with ptr to object
ENDIF
ENDIF
IFDIF <Msg>,<dx> ;If msg number not in DX
mov dx,Msg ;Put it in DX
ENDIF
call sendMsg ;Send message
IFNB <ArgList> ;If arguments
X = 0 ;Init stack depth counter
IRP Arg,<ArgList> ;For every arg on stack
X = X+2 ;Increment depth counter
ENDM
add sp,X ;Reset stack pointer
ENDIF
ENDM
COMMENT % ===============================================================
Pushes up to ten arguments onto the stack.
=========================================================================%
pushArgs MACRO A0,A1,A2,A3,A4,A5,A6,A7,A8,A9
IFB <A0> ;If no more arguments
EXITM ;Exit macro
ENDIF
IFIDN <A0>,<ax> ;If arg in AX
push ax ;Push AX
ELSE
IFIDN <A0>,<bx> ;If arg in BX
push bx ;Push BX
ELSE
IFIDN <A0>,<cx> ;If arg in CX
push cx ;Push CX
ELSE
IFIDN <A0>,<dx> ;If arg in DX
push dx ;Push DX
ELSE
mov bx,A0 ;Else move into BX
push bx ;Push BX
ENDIF
ENDIF
ENDIF
ENDIF
pushArgs A1,A2,A3,A4,A5,A6,A7,A8,A9
ENDM
COMMENT % =============================================================
Finds the specified message for specified object.
Passed: Msg - Message number; Obj - Addr ptr to object structure
Passes: si - Pointer to combined method pointer
=========================================================================%
findMsg MACRO Obj,Msg,Lbl
LOCAL fdmg1,fdmg2
IFDIF <Obj>,<si> ;If object ptr is not in SI
mov si,Obj ;Put it there
ENDIF
mov di,Wptr[si].Instances
;Addr of msg tbl end
mov si,Wptr[si].Messages
;Addr of msg tbl beginning
fdmg1: lodsb ;Fetch msg number
eq al,Msg,fdmg2 ;Exit if message is found
add si,2 ;Else point to next message
cmp si,di ;More messages?
jb fdmg1 ;If so continue search
IFNB <Lbl> ;If label provided
jmp Lbl ;Jump to it upon failure
ENDIF
fdmg2:
ENDM
Source File: objects.asm
PUBLIC sendMsg
COMMENT % ===================================================================
Sends the specified object the given message. This causes the execution of
the combined message for the object.
Passed: dx - Message number; si - Combined method ptr
=============================================================================%
sendMsg PROC NEAR
findMsg si,dl,smg2 ;Search for message
mov si,Wptr[si] ;Get method addr
mov cx,Wptr[si] ;Get method count
smg1: add si,2 ;Point to method
pushData <cx,si> ;Save loop cnt, addr ptr
call Wptr[si] ;Execute method
popData <si,cx> ;Restore addr ptr, loop cnt
loop smg1 ;Loop
smg2: ret
sendMsg ENDP
[LISTING TWO]
Include File: objects.inc
COMMENT % ==================================================================
Data structure used to hold pointers to an object's ancestors, messages, and
instance variables.
===========================================================================%
_Object STRUC
Objects DW Nil
Messages DW Nil
Instances DW Nil
_Object ENDS
Macro File: objects.mac
COMMENT % ===================================================================
Defines an object.
Passed: Obj - Object name; Objs - Ancestor list; Instances - Instance
variable list; Messages - Message list
=============================================================================%
defObj MACRO Obj,Objs,Instances,Messages
LOCAL ObjTbl,MsgTbl,InstTbl
ObjTbl LABEL WORD
objsDef Obj,<Objs>
MsgTbl LABEL WORD
msgsDef Obj,<Messages>
InstTbl LABEL WORD
instDef <Instances>
ALIGN 2
PUBLIC Obj
Obj _Object <ObjTbl,MsgTbl,InstTbl>
ENDM
COMMENT % ===================================================================
Defines objects.
Passed: Obj - Object name; Objs - Ancestor list
=============================================================================%
objsDef MACRO Obj,Objs
DW Obj
IRP Obj,<Objs>
DW Obj
ENDM
ENDM
COMMENT % ====================================================================
Defines messages.
Passed: Obj - Object name; Messages - Message list
=============================================================================%
msgsDef MACRO Obj,Messages
IRP Msg,<Messages>
DB Msg ;Msg# identifies msg
IFNDEF Obj&&Msg
DW Nil ;Obj has no local methods
ELSE
DW Obj&&Msg ;Obj has local methods
ENDIF
ENDM
ENDM
COMMENT % ===================================================================
Defines instances variables.
Passed: Instances - Instance variable list
=============================================================================%
instDef MACRO Instances
X = 0
Y = 0
IRP Inst,<Instances>
defInst Inst,%X,%Y
ENDM
ENDM
COMMENT % ====================================================================
Defines an instance variable.
Passed: Inst - Instance variable name; Cnt - Instance variable field number;
Size - Size of instance variable
=============================================================================%
defInst MACRO Inst,Cnt,Size
IFIDN <Cnt>,<0>
X = X+1
ELSE
IFIDN <Cnt>,<1>
X = X+1
Y = Inst
ELSE
X = 0
defVar Size,Inst
ENDIF
ENDIF
ENDM
COMMENT % ====================================================================
Defines a data item.
Passed: Size - Size of data in bytes; Value - Value of data item
=============================================================================%
defVar MACRO Size,Value
IFIDN <Size>,<1>
DB Value
ELSE
IFIDN <Size>,<2>
DW Value
ELSE
IFIDN <Size>,<4>
DD Value
ELSE
IFIDN <Size>,<8>
DQ Value
ELSE
IFIDN <Size>,<10>
DT Value
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDM
[LISTING THREE]
Include File: objects.inc
COMMENT % ==================================================================
Data structure used to hold pointers to a message's Before, Primary, and
After methods.
===========================================================================%
_Message STRUC
Before DW Nil
Primary DW Nil
After DW Nil
_Message ENDS
Macro File: objects.mac
COMMENT % ====================================================================
Defines a message.
Passed: Obj - Object name; Msg - Message name; Methods - Method list
=============================================================================%
defMsg MACRO Obj,Msg,Methods
ALIGN 2
Obj&Msg _Message <Methods>
ENDM
[LISTING FOUR]
Macro File: objects.mac
COMMENT % ====================================================================
Sets us SI to point to object, and calls initObject procedure.
=============================================================================%
initObj MACRO Obj
lea si,Obj ;Pass object ptr
call initObject ;Find all ancestors
ENDM
Source File: objects.asm
PUBLIC initObject
COMMENT % ====================================================================
Initializes an object by flattening its inheritance lattice to create
combined methods for its messages.
Passed: si - Addr ptr to object structure
=============================================================================%
initObject PROC NEAR
lea di,Buffer ;Get buffer addr
call findAncestors ;Find/Save all ancestors
call evalMsgs ;Evaluate messages
ret
initObject ENDP
COMMENT % ====================================================================
Finds all of an object's ancestors and saves them for use by the message
evaluator.
Passed: bx - Addr ptr to message table (end of object table); di - Addr ptr
to temporary object table; si - Addr ptr to object structure
=============================================================================%
findAncestors PROC NEAR
pushData <bx,si> ;Save obj ptr
mov bx,Wptr[si].Messages ;Get addr ptr to msg tbl
mov si,Wptr[si].Objects ;Get addr of object tbl
movsw ;Move obj ptr
fas1: eq bx,si,fas2 ;Exit if end of tbl
push si
mov si,Wptr[si] ;Get next object
call findAncestors ;Find others
pop si
add si,2
jmp fas1 ;More in tbl - Loop
fas2: mov Wptr[di],Nil ;Mark end of list
popData <si,bx> ;Restore obj ptr
ret
findAncestors ENDP
COMMENT % ====================================================================
Creates combined methods for all of an object's messages.
Passed: si - Addr ptr to object structure
=============================================================================%
evalMsgs PROC NEAR
mov bx,Wptr[si].Messages ;Get addr of message tbl
mov cx,Wptr[si].Instances ;Get addr of instance tbl
ems1: mov dl,Bptr[bx] ;Get msg number
xor dh,dh
call combineMethods ;Combine methods
add bx,3 ;Point to next tbl entry
neq bx,cx,ems1 ;More in tbl? - loop
ret
evalMsgs ENDP
COMMENT % ====================================================================
Combines methods for all included objects.
Passed: dx - Message number; si - Addr ptr to object structure
=============================================================================%
combineMethods PROC NEAR
push bx
mov ?Compiled,Nil ;Clear compiled flag
mov bx,Wptr[CompileStart] ;Get start of combined mthd
mov Wptr[CompilePtr],bx ;Init location ptr
mov di,Nil ;Zero count word
call saveMethodAddr ;Save value
call saveBefores ;Save Before methods
mov bx,Primary ;Select Primary method type
lea di,Buffer ;Get addr of tmp object tbl
mov di,Wptr[di] ;Get tbl entry
call saveMethod ;Save method
call saveAfters ;Save After methods
null ?Compiled,cms1 ;Nothing compiled? - Exit
call updatePtrs ;Update message, location ptrs
cms1: pop bx
ret
combineMethods ENDP
COMMENT % ====================================================================
Updates the message and location pointers.
Passed: dx - Message number; si - Addr ptr to object structure
=============================================================================%
updatePtrs PROC NEAR
push si
findMsg si,dl ;Find message
mov di,Wptr[CompileStart] ;Get ptr to combined method
mov Wptr[si],di ;Change message ptr
mov bx,Wptr[CompilePtr] ;Get current compile location
mov Wptr[CompileStart],bx ;Reset start of combined mthd
pop si
ret
updatePtrs ENDP
COMMENT % ====================================================================
Save the Before method type for the specified object.
Passed: dx - Message number
=============================================================================%
saveBefores PROC NEAR
push si
mov bx,Before ;Select Before method type
lea si,Buffer ;Get addr of tmp object tbl
mov di,Wptr[si] ;Get tbl entry
sbs1: call saveMethod ;Save method
add si,2 ;Point to next tbl entry
mov di,Wptr[si] ;Get next tbl entry
identity di,sbs1 ;More in table? - loop
pop si
ret
saveBefores ENDP
COMMENT % ===================================================================
Save the After method type for the specified object.
Passed: dx - Message number
=============================================================================%
saveAfters PROC NEAR
pushData <cx,si>
mov bx,After ;Select After method type
lea si,Buffer ;Get addr of tmp object tbl
mov cx,si ;Save addr of object tbl
sas1: mov ax,Wptr[si] ;Get tbl entry
null ax,sas2 ;Null? - End of tbl, exit
add si,2 ;Point to next tbl entry
jmp sas1 ;Loop
sas2: sub si,2 ;Point to previous tbl entry
mov di,Wptr[si] ;Get next tbl entry
call saveMethod ;Save method
neq si,cx,sas2
popData <si,cx>
ret
saveAfters ENDP
COMMENT % ====================================================================
Save the specified method for specified object.
Passed: bx-Method type; di-Addr ptr to object structure; dx-Message number
=============================================================================%
saveMethod PROC NEAR
pushData <bx,di,si>
findMsg di,dl,svm3 ;Find message
mov di,Wptr[si] ;Get method tbl addr ptr
null di,svm3 ;Exit if no local methods
mov di,Wptr[di+bx] ;Get method addr ptr
null di,svm3 ;Exit if no message
mov bx,Wptr[CompileStart] ;Get start of combined mthd
svm1: eq bx,Wptr[CompilePtr],svm2
eq di,Wptr[bx],svm3 ;Exit if duplicate method
add bx,2 ;Point to next addr
jmp svm1 ;Check next addr
svm2: call saveMethodAddr ;Save method addr
svm3: popData <si,di,bx>
ret
saveMethod ENDP
COMMENT % ====================================================================
Save value at current compile location, and increments location pointer.
Passed: di - Value to store
=============================================================================%
saveMethodAddr PROC NEAR
mov ?Compiled,1 ;Set compiled flag
mov bx,Wptr[CompilePtr] ;Get ptr to combined mthd end
mov Wptr[bx],di ;Save value
add bx,2 ;Point to next location
mov Wptr[CompilePtr],bx ;Reset location ptr
mov bx,Wptr[CompileStart] ;Get ptr mthd count
mov di,Wptr[bx] ;Get mthd count
inc di ;Increments mthd count
mov Wptr[bx],di ;Save value
ret
saveMethodAddr ENDP
[LISTING FIVE]
Macro File: objects.mac
COMMENT % ====================================================================
Gets an object's instance variable.
Passed: Dest- Destination register; Var - Instance variable name;
Obj - Source object
=============================================================================%
getInst MACRO Dest,Var,Obj
IFNB <Obj>
IFIDN <Obj>,<Self>
mov si,WORD PTR[Self]
mov si,WORD PTR[si].Instances
ELSE
IFIDN <si>,<Obj>
mov si,WORD PTR[si].Instances
ELSE
mov si,Obj&.Instances
ENDIF
ENDIF
ENDIF
mov Dest,[si+Var]
ENDM
COMMENT % ====================================================================
Sets an object's instance variable.
Passed: Var - Instance variable name; Source - Source register; Obj - Source
object; Size - Size of data
=============================================================================%
setInst MACRO Var,Source,Obj,Size
IFNB <Obj>
IFIDN <Obj>,<Self>
mov si,WORD PTR[Self]
mov si,WORD PTR[si].Instances
ELSE
mov si,Obj&.Instances
ENDIF
ENDIF
setInst_ Var,Source,Size
ENDM
COMMENT % ====================================================================
Assembles move instruction based on source register.
=============================================================================%
setInst_ MACRO Var,Source,Size
IFIDN <Source>,<al>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<ah>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<bl>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<bh>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<cl>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<ch>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<dl>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<dh>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Source>,<ax>
mov WORD PTR[si+Var],Source
ELSE
IFIDN <Source>,<bx>
mov WORD PTR[si+Var],Source
ELSE
IFIDN <Source>,<cx>
mov WORD PTR[si+Var],Source
ELSE
IFIDN <Source>,<dx>
mov WORD PTR[si+Var],Source
ELSE
IFIDN <Source>,<di>
mov WORD PTR[si+Var],Source
ELSE
IFIDN <Source>,<si>
mov WORD PTR[si+Var],Source
ELSE
IFIDN <Size>,<1>
mov BYTE PTR[si+Var],Source
ELSE
IFIDN <Size>,<2>
mov WORD PTR[si+Var],Source
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDM
[LISTING SIX]
Macro File: objects.mac
COMMENT % ====================================================================
Gets an object's instance variable, but object is pointed to by one of
Self's instance variables.
Passed: Dest- Destination register; Var - Instance variable name;
Obj - Source object instance variable
=============================================================================%
getInst$ MACRO Dest,Var,Obj
mov si,WORD PTR[Self]
mov si,WORD PTR[si].Instances
mov si,[si+Obj]
mov si,WORD PTR[si].Instances
mov Dest,[si+Var]
ENDM
COMMENT % ====================================================================
Sets an object's instance variable, but object is pointed to by one of
Self's instance variables.
Passed: Var - Instance variable name; Source - Source register; Obj - Source
object instance variable; Size - Size of data
=============================================================================%
setInst$ MACRO Var,Source,Obj,Size
mov si,WORD PTR[Self]
mov si,WORD PTR[si].Instances
mov si,[si+Obj]
mov si,WORD PTR[si].Instances
setInst_ Var,Source,Size
ENDM
[Example 1]
send Screen,Refresh,DoubleBdr ;Send Screen a Refresh msg
send Self,Read ;Send Self a Read msg
send Self,<WORD PTR[bx]> ;Send Self msg pointed to by
; BX register
[Example 2]
defObj Window,\ ;Define Window object
<>,\ ;As a base object
<>,\ ;With no inst vars
<Refresh> ;Responds to Refresh msg
defObj Border,\ ;Define Border object
<>,\ ;As a base object
<>,\ ;With no inst vars
<Refresh> ;Responds to Refresh msg
defObj Screen,\ ;Define Screen object
<Window,Border>,\ ;As a derived object
<Row1,1,1,\ ;With these inst vars
Col1,1,0,\
Row2,1,23,\
Col2,1,79,\
Color,1,34h,\
BdrColor,1,30h,\
MemSeg,2,Nil>,\
<Refresh> ;Responds to Refresh msg
[Example 3]
defMsg Window,\ ;Define for Window object
Refresh,\ ;The Refresh msg
<clrWin,,> ;To clear window
defMsg Border,\ ;Define for Border object
Refresh,\ ;The Refresh msg
<,,drawBdr> ;To draw border
defMsg Screen,\ ;Define for Screen object
Refresh,\ ;The Refresh msg
<,drawBackDrop,drawLabel>
;To draw back drop and label
[Example 4]
defMsg Label,\ ;Define for Label object
Refresh,\ ;The Refresh msg
<,,drawLabel> ;To draw label
defObj label,\ ;Define Label object
<>,\ ;As a base object
<>,\ ;With no inst vars
<Refresh> ;Responds to Refresh msg
defMsg Screen,\ ;Define for Screen object
Refresh,\ ;The Refresh msg
<,drawBackDrop,> ;To draw back drop
defObj Screen,\ ;Define Screen object
<Window,Border,Label>,\
;As a derived object
<Row1,1,1,\ ;With these inst vars
Col1,1,0,\
Row2,1,23,\
Col2,1,79,\
Color,1,34h,\
BdrColor,1,30h,\
MemSeg,2,Nil>,\
<Refresh> ;Responds to Refresh msg
[Example 5]
initObj Screen ;Combine methods for Screen
[Example 6]
getInst bl,Color,Screen ;Fetch Screen color
setInst BdrColor,bl ;Copy it to BdrColor
setInst Color,bl,Self ;And Self's color
[Example 7]
getInst$ bl,Color,Master ;Fetch color from object
; pointed to by Master
setInst Color,bl,Self ;Copy it to Self's color